package com.glasgowrax.hack.util;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import android.util.Log;

import com.glasgowrax.hack.domain.CycleRacksGeoJson;
import com.glasgowrax.hack.domain.Feature;
import com.glasgowrax.hack.domain.LatLng;

public class LocationUtil {

	public static List<Feature> getNearestBikeRacks(int number, CycleRacksGeoJson cycleRacksGeoJson,
			LatLng target) {
		List<Feature> features = cycleRacksGeoJson.getFeatures();
		Map<Feature, Double> featureMap = findDistances(features, target);
        ValueComparator comparator =  new ValueComparator(featureMap);
        TreeMap<Feature, Double> sortedFeatures = new TreeMap<Feature, Double>(comparator);
        sortedFeatures.putAll(featureMap);
        List<Feature> nearestRacks = new ArrayList<Feature>();
        for (int i = 0; i < number; ++i) {
        	Log.i("LOCATIONS", ""+sortedFeatures.size());
        	
        	Feature key = sortedFeatures.firstKey();
        	
        	nearestRacks.add(key);
        	sortedFeatures.remove(key);
        }
		return nearestRacks;
	}

	private static Map<Feature, Double> findDistances(List<Feature> features, LatLng target) {
		Map<Feature, Double> featureMap = new HashMap<Feature, Double>();
		for (Feature feature : features) {
			double[] coordinates = feature.getGeometry().getCoordinates();
			LatLng rackPosition = new LatLng(coordinates[1], coordinates[0]); // longitude first
			featureMap.put(feature, getDistance(rackPosition, target));
		}
		return featureMap;
	}

	private static double getDistance(LatLng a, LatLng b) {
		double verticalDifference = a.getLongitude() - b.getLongitude();
		double horizontalDifference = a.getLatitude() - b.getLatitude();
		return Math.sqrt((verticalDifference * verticalDifference) +
				(horizontalDifference * horizontalDifference));
	}
}

class ValueComparator implements Comparator<Feature> {

    Map<Feature, Double> base;
    public ValueComparator(Map<Feature, Double> base) {
        this.base = base;
    }

    // Note: this comparator imposes orderings that are inconsistent with equals.    
    public int compare(Feature a, Feature b) {
        if (base.get(a) < base.get(b)) {
            return -1;
        } else if (base.get(a) > base.get(b)) {
            return 1;
        } else {
        	return 0;
        }
    }
}